home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Sprite 1984 - 1993
/
Sprite 1984 - 1993.iso
/
src
/
boot
/
netBoot.new
/
dev
/
xd.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-12-19
|
8KB
|
347 lines
#ifndef lint
/* static char sccsid[] = "@(#)xd.c 1.0 86/03/12 Copyr 1986 Sun Micro";*/
#endif
/*
* Copyright (c) 1986 by Sun Microsystems, Inc.
*/
/* Standalone driver for Xylogics 751 */
#ifndef M25
#include "../dev/saio.h"
#include "../h/param.h"
#include "../dev/dkbad.h"
#include "../dev/dklabel.h"
#include "../dev/dkio.h"
#include "../h/fsdir.h"
#include "../dev/xdcreg.h"
#include "../dev/xdreg.h"
extern char msg_nolabel[];
struct xdparam {
unsigned short xd_boff; /* Cyl # starting partition */
unsigned short xd_nsect; /* Sect/track */
unsigned short xd_ncyl; /* Cyl/disk */
unsigned short xd_nhead; /* Heads/cyl */
unsigned short xd_bhead; /* Base head # for removable disk */
unsigned short xd_drive; /* Xylogics drive type ID */
int xd_nblk;
int xd_badaddr; /* Disk block # of bad-block table */
struct dkbad xd_bad;
unsigned char xd_unit;
};
#define CYL(p) (p*xdp->xd_nsect*xdp->xd_nhead) /* cyl to block conv */
#define NSTD 2
#define TIMEOUT 0x2ffff
unsigned long xdstd[NSTD] = { 0xee80, 0xee88 };
/*
* Structure of our DMA area
*/
#define MAXBSIZE 8192
struct xddma {
struct xdiopb xdiopb;
char xdblock[MAXBSIZE]; /* R/W data */
};
/*
* What resources we need to run
*/
struct devinfo xdinfo = {
sizeof (struct xddevice),
sizeof (struct xddma),
sizeof (struct xdparam),
NSTD,
xdstd,
MAP_MBIO,
#ifdef BOOTBLOCK
DEV_BSIZE,
#else
DEV_BSIZE, /* MAXBSIZE, */
#endif
};
/*
* What facilities we export to the world
*/
int xdopen(), xdstrategy();
extern int xxboot(), xxprobe();
extern int nullsys();
struct boottab xddriver = {
"xd", xxprobe, xxboot, xdopen, nullsys, xdstrategy,
"\0", &xdinfo,
};
/*
* Open a xdlogics disk.
*/
xdopen(sip)
register struct saioreq *sip;
{
register struct xdparam *xdp;
register struct xddevice *xdaddr;
register struct xdiopb *xd;
struct dk_label *label;
register int t;
u_short ppart;
#ifndef BOOTBLOCK
int xdspin();
#endif !BOOTBLOCK
xdp = (struct xdparam *)sip->si_devdata;
xdaddr = (struct xddevice *)sip->si_devaddr;
xd = &((struct xddma *)sip->si_dmaaddr)->xdiopb;
xdp->xd_unit = sip->si_unit & 0x03;
ppart = (sip->si_unit >> 2) & 1;
/* reset controller */
xdaddr->xd_csr = XD_RST;
DELAY(300);
xdp->xd_boff = 0; /* Don't offset block numbers */
xdp->xd_nsect = 2;
xdp->xd_nhead = 2;
xdp->xd_ncyl = 2;
xdp->xd_bad.bt_mbz = -1;
#ifndef BOOTBLOCK
/*
* Wait for disk to spin up, if necessary.
*/
if (!isspinning(xdspin, (char *)sip, 0))
return (-1);
#endif !BOOTBLOCK
label = (struct dk_label *)
((struct xddma *)sip->si_dmaaddr)->xdblock;
label->dkl_magic = 0;
if (xdcmd(XD_READ, sip, 0, (char *)label, 1))
goto badopen;
if (chklabel(label))
goto badopen;
if (ppart != label->dkl_ppart)
goto badopen;
goto foundlabel;
badopen:
printf(msg_nolabel);
return (-1);
foundlabel:
xdp->xd_nhead = label->dkl_nhead;
xdp->xd_nsect = label->dkl_nsect;
xdp->xd_ncyl = label->dkl_ncyl + label->dkl_acyl;
xdp->xd_boff = label->dkl_map[sip->si_boff].dkl_cylno;
xdp->xd_nblk = label->dkl_map[sip->si_boff].dkl_nblk;
if (xdcmd(XD_WPAR, sip, 0, 0, 0))
printf("xd: init error %x\n", xd->xd_errno);
/*
* Fetch bad block info.
*/
xdp->xd_badaddr = ((int)xdp->xd_ncyl * xdp->xd_nhead - 1)
* xdp->xd_nsect;
if (xdcmd(XD_READ, sip, xdp->xd_badaddr, (char *)&xdp->xd_bad, 1))
printf("xd: no bad block info\n");
return (0);
}
xdstrategy(sip, rw)
struct saioreq *sip;
int rw;
{
register int cmd = (rw == WRITE) ? XD_WRITE : XD_READ;
register int boff;
register struct xdparam *xdp = (struct xdparam *)sip->si_devdata;
register short nsect;
#ifndef BOOTBLOCK
char *ma;
int i, bn;
#endif BOOTBLOCK
boff = CYL(xdp->xd_boff);
#ifdef BOOTBLOCK
/* assert si_cc == DEV_BSIZE */
if (xdcmd(cmd, sip, sip->si_bn + boff, sip->si_ma, 1))
return (-1);
return (sip->si_cc);
#else BOOTBLOCK
nsect = sip->si_cc / DEV_BSIZE;
if (sip->si_bn + nsect > xdp->xd_nblk)
nsect = xdp->xd_nblk - sip->si_bn;
if (nsect == 0)
return (0);
if (xdcmd(cmd, sip, sip->si_bn+boff, sip->si_ma, nsect) == 0)
return (nsect*DEV_BSIZE);
/*
* Large transfer failed, now do one at a time
*/
bn = sip->si_bn + boff;
ma = sip->si_ma;
for (i = 0; i < nsect; i++) {
if (xdcmd(cmd, sip, bn, ma, 1))
return (-1);
bn++;
ma += DEV_BSIZE;
}
return (nsect*DEV_BSIZE);
#endif BOOTBLOCK
}
#ifndef BOOTBLOCK
/*
* This routine is called from isspinning() as the test condition.
*/
int
xdspin(sip, dummy)
struct saioreq *sip;
int dummy;
{
register struct xdparam *xdp = (struct xdparam *)sip->si_devdata;
register struct xdiopb *xd = &((struct xddma *)sip->si_dmaaddr)->xdiopb;
(void) xdcmd(XD_RESTORE, sip, 0, (char *)0, 0);
return ((xd->xd_dstat & XD_READY) ? 1 : 0);
}
#endif !BOOTBLOCK
xdcmd(cmd, sip, bno, buf, nsect)
int cmd;
struct saioreq *sip;
register int bno;
char *buf;
int nsect;
{
register int i, t;
register struct xdparam *xdp = (struct xdparam *)sip->si_devdata;
register struct xdiopb *xd = &((struct xddma *)sip->si_dmaaddr)->xdiopb;
register struct xddevice *xdaddr = (struct xddevice *)sip->si_devaddr;
register char *bp = ((struct xddma *)sip->si_dmaaddr)->xdblock;
unsigned short cylno, sect, head;
int error, errcnt = 0;
int timeout = 0;
int firstime = 1;
cylno = bno / CYL(1);
sect = bno % xdp->xd_nsect;
head = (bno / xdp->xd_nsect) % xdp->xd_nhead;
if (cmd == XD_WRITE && buf != bp) /* Many just use common buf */
bcopy(buf, bp, nsect*DEV_BSIZE);
retry:
bzero((char *)xd, sizeof (struct xdiopb));
xd->xd_cmd = cmd >> 8;
switch (cmd) {
case XD_WPAR:
xd->xd_subfunc = XD_DRIVE;
xd->xd_drparam = 0;
xd->xd_nsect = (short) ((xdp->xd_nsect - 1) << 8);
xd->xd_cylinder = xdp->xd_ncyl - 1;
xd->xd_head = xdp->xd_nhead - 1;
xd->xd_sector = xdp->xd_nsect - 1;
break;
default:
xd->xd_subfunc = 0;
xd->xd_nsect = nsect;
xd->xd_cylinder = cylno;
xd->xd_head = head;
xd->xd_sector = sect;
xd->xd_bufaddr = (int) (MB_DMA_ADDR(bp));
}
xd->xd_unit = xdp->xd_unit & 3;
xd->xd_intpri = 0; /* disable interrupt */
xd->xd_bufmod = XD_ADDRMOD24; /* standard supervisory */
t = (int) (MB_DMA_ADDR(xd));
xdaddr->xd_iopbaddr1 = (int) t;
xdaddr->xd_iopbaddr2 = (int) t >> 8;
xdaddr->xd_iopbaddr3 = (int) t >> 16;
xdaddr->xd_iopbaddr4 = (int) t >> 24;
xdaddr->xd_modifier = XD_ADDRMOD24;
xdaddr->xd_csr = XD_AIO;
while (!(xdaddr->xd_csr & XD_RIO) && timeout < TIMEOUT)
timeout++;
if (timeout == TIMEOUT) {
/*
* kludge for the 751 prototype. this
* doesn't hurt in the normal case and we
* didn't wanted to risk another prom release.
* so here it is.
*/
if (firstime && cmd == XD_RESTORE) {
xdaddr->xd_csr = XD_RST;
DELAY(300);
firstime = 0;
timeout = 0;
goto retry;
}
printf("disk ctlr timeout cmd %x\n", cmd);
xdaddr->xd_csr = XD_RST; /* reset the controller */
return(-1);
}
if (xdaddr->xd_csr & XD_FERR) {
xdaddr->xd_csr = XD_RST;
DELAY(300);
xd->xd_iserr = 1;
}
xdaddr->xd_csr = XD_CLRIO; /* clear rio bit */
xdaddr->xd_csr = XD_CLRBS; /* release register */
if (xd->xd_iserr && xd->xd_errno != XDE_FECC) {
if (nsect != 1) /* only try hard on single sectors */
return (-1);
error = xd->xd_errno;
if ((i = xdfwd(xdp, cylno, head, sect)) != 0)
return xdcmd(cmd, sip, i, buf, 1);
/* Attempt to reset the error condition */
if (cmd != XD_RESTORE) {
xdaddr->xd_csr = XD_RST; /* reset the controller */
DELAY(300); /* and then the drive */
(void) xdcmd(XD_RESTORE, sip, 0, (char *)0, 1);
}
if (++errcnt < 5)
goto retry;
if (bno != 0) /* drive type probe */
printf("xd: error %x bno %d\n", error, bno);
return (-1); /* Error */
}
if (cmd == XD_READ && buf != bp) /* Many just use common buf */
bcopy(bp, buf, nsect*DEV_BSIZE);
return (0);
}
xdfwd(xdp, cn, tn, sn)
register struct xdparam *xdp;
int cn, tn, sn;
{
register struct dkbad *bt = &xdp->xd_bad;
register int i;
if (bt->bt_mbz != 0) /* not initialized */
return (0);
for (i=0; i<126; i++) /* FIXME constant */
if (bt->bt_bad[i].bt_cyl == cn &&
bt->bt_bad[i].bt_trksec == (tn<<8)+sn) {
return (xdp->xd_badaddr - i - 1);
}
return (0);
}
#endif M25